package cn.iocoder.an.module.business.job;

import cn.iocoder.an.framework.common.util.object.BeanUtils;
import cn.iocoder.an.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.an.framework.quartz.core.handler.JobHandler;
import cn.iocoder.an.framework.tenant.core.job.TenantJob;
import cn.iocoder.an.module.business.controller.admin.equipmentmanage.vo.EquipmentManageRespVO;
import cn.iocoder.an.module.business.dal.dataobject.equipmentcheckplan.EquipmentCheckPlanDO;
import cn.iocoder.an.module.business.dal.dataobject.equipmentmanage.EquipmentManageDO;
import cn.iocoder.an.module.business.dal.dataobject.equipmnetkeepwait.EquipmnetKeepWaitDO;
import cn.iocoder.an.module.business.dal.dataobject.warningconfig.WarningConfigDO;
import cn.iocoder.an.module.business.dal.mysql.equipmentcheckplan.EquipmentCheckPlanMapper;
import cn.iocoder.an.module.business.dal.mysql.equipmentmanage.EquipmentManageMapper;
import cn.iocoder.an.module.business.dal.mysql.equipmnetkeepwait.EquipmnetKeepWaitMapper;
import cn.iocoder.an.module.business.dal.mysql.warningconfig.WarningConfigMapper;
import cn.iocoder.an.module.business.utils.WeComMessageUtil;
import cn.iocoder.an.module.system.api.notify.NotifyMessageSendApi;
import cn.iocoder.an.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
import cn.iocoder.an.module.system.dal.dataobject.dict.DictDataDO;
import cn.iocoder.an.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.an.module.system.service.dict.DictDataService;
import cn.iocoder.an.module.system.service.user.AdminUserService;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class CheckMessageSendJob implements JobHandler {

    @Resource
    private WarningConfigMapper warningConfigMapper;

    @Resource
    private EquipmnetKeepWaitMapper equipmnetKeepWaitMapper;

    @Resource
    private AdminUserService userService;

    @Autowired
    private WeComMessageUtil weComMessageUtil;

    @Resource
    private NotifyMessageSendApi notifySendApi;

    @Resource
    private DictDataService dictDataService;

    @Resource
    private EquipmentCheckPlanMapper equipmentCheckPlanMapper;

    @Resource
    private EquipmentManageMapper equipmentManageMapper;


    @Override
    @TenantJob // 标记多租户
    public String execute(String param) throws Exception {


        //1.先获取预警配置项 按照预警天数从小到大排序
        LambdaQueryWrapperX<WarningConfigDO> configWrapper = new LambdaQueryWrapperX<>();
        configWrapper.eq(WarningConfigDO::getWarningType, 2);
        configWrapper.orderByAsc(WarningConfigDO::getWarningDays);
        List<WarningConfigDO> configList = warningConfigMapper.selectList(configWrapper);

        LambdaQueryWrapperX<EquipmentManageDO> equipmentManageWrapper = new LambdaQueryWrapperX<>();
        equipmentManageWrapper.isNotNull(EquipmentManageDO::getLastCheckTime);
        List<EquipmentManageDO> equipmentManageDOS = equipmentManageMapper.selectList(equipmentManageWrapper);
        List<EquipmentManageRespVO> list = BeanUtils.toBean(equipmentManageDOS, EquipmentManageRespVO.class);


        for (EquipmentManageRespVO respVO : list) {
            if (respVO.getLastCheckTime() == null) {
                continue;
            }

            //3. 查询待点检计划
            LambdaQueryWrapperX<EquipmentCheckPlanDO> planWrapper = new LambdaQueryWrapperX<>();
            // 添加条件：绑定了设备类型的
            planWrapper.isNotNull(EquipmentCheckPlanDO::getEquipmentTypeId);
            planWrapper.likeIfPresent(EquipmentCheckPlanDO::getEquipmentTypeName, respVO.getEquipmentClassifyName());
            planWrapper.orderByAsc(EquipmentCheckPlanDO::getCreateTime);
            List<EquipmentCheckPlanDO> planDOList = equipmentCheckPlanMapper.selectList(planWrapper);

            //使用点检频率和上次点检时间 计算下次点检时间  如果下次点检时间减去当前时间小于预警小时 提醒
            Long equipmentClassify = respVO.getEquipmentClassify();
            for (EquipmentCheckPlanDO planDO : planDOList) {
                List<Long> equipmentTypeId = planDO.getEquipmentTypeId();
                // 判断 equipmentClassify 是否在 equipmentTypeId 中
                if (equipmentTypeId != null && equipmentClassify != null && equipmentTypeId.contains(equipmentClassify)) {
                    System.out.println("equipmentClassify 在列表中");
                    //点检频率
                    Integer checkRepeat = planDO.getCheckRepeat().intValue();
                    //上次点检时间
                    LocalDateTime lastCheckTime = respVO.getLastCheckTime();
                    //下次点检按时间
                    LocalDateTime nextCheckTime = lastCheckTime.plusHours(checkRepeat);
                    LocalDateTime now = LocalDateTime.now();
                    // 计算从 now 到 nextCheckTime 之间的小时数（向下取整）
                    long remainingHours = Duration.between(now, nextCheckTime).toHours();
                    //保留小数（比如 2.5 小时），可以用下面的方法
                    double remainingHoursWithDecimal = Duration.between(now, nextCheckTime).toMillis() / (1000.0 * 60 * 60);
                    for (WarningConfigDO config : configList) {
                        //预警小时
                        Integer warningDays = config.getWarningDays();
                        // 预警一次 避免重复预警
                        if (remainingHoursWithDecimal <= warningDays) {
                            respVO.setColor(config.getWarningColor());
                            sendKeepMessage(config.getWarningUser(),respVO,nextCheckTime);
                            break;
                        }
                    }

                }

            }

        }
        return "success";
    }

    public void sendKeepMessage(List<Long> dutyUserId,EquipmentManageRespVO equipmentManageDO,LocalDateTime nextCheckTime) {
        //推送消息
        List<AdminUserDO> userList = userService.getUserList(dutyUserId);
        String userIds = "";
        StringBuilder userIdBuilder = new StringBuilder();

        // 获取当前时间并格式化
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedNow = nextCheckTime.format(formatter);

        for (AdminUserDO user : userList) {
            String userId = weComMessageUtil.getUserIdByMobile(user.getEnterpriseWeChatAccount());
            if (userId != null && !userId.trim().isEmpty()) {
                // 如果已经有内容了，先添加分隔符
                if (userIdBuilder.length() > 0) {
                    userIdBuilder.append("|");
                }
                userIdBuilder.append(userId);
            }
        }

        // 将 StringBuilder 转换为最终的字符串
        userIds = userIdBuilder.toString();
        // 可选：检查最终结果是否为空
        if (userIds.isEmpty()) {
            // 处理没有找到任何有效用户ID的情况
            System.out.printf("没有找到任何有效的企业微信 UserID");
            return;
        }

        // 1. 使用 sendTextMessage 方法 (更灵活，可以同时指定用户、部门、标签)

        //从字典配置中获取发送的消息
        DictDataDO wxMessage = dictDataService.getDictData("by_message", "3");
        String text = "设备点检预警通知：您有新的设备待点检，设备编号如下：【" + equipmentManageDO.getCode() +  "】，设备安装位置：【"+equipmentManageDO.getInstallPosition()+"】，计划点检时间为：" + nextCheckTime +"请规划时间完成设备点检工作。";

        String systemMessage =text + formattedNow ;
          // 将时间戳添加到消息中
        WeComMessageUtil.WeComSendResult weComSendResult = weComMessageUtil.sendTextMessage(systemMessage, userIds, null, null);
        System.out.printf("推送结果:" + weComSendResult.toString());

    }


}
